package personal.parser;


import java.util.List;
import java.util.Set;

/**
 * 文法
 */
public interface Grammar {

    /**
     * 符号
     */
    class Symbol {
        private final String expression;

        public String getExpression() {
            return expression;
        }

        protected Symbol(String expression) {
            this.expression = expression;
        }

        @Override
        public String toString() {
            return expression;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null || this.getClass() != obj.getClass()) return false;
            return this.expression.equals(((Symbol) obj).expression);
        }

        @Override
        public int hashCode() {
            return this.expression.hashCode();
        }
    }

    /**
     * 终结符
     */
    class Terminal extends Symbol {
        public Terminal(String expression) {
            super(expression);
        }
    }

    /**
     * 非终结符
     */
    class NonTerminal extends Symbol {
        public NonTerminal(String expression) {
            super(expression);
        }
    }

    final Terminal EMPTY = new Terminal("ε");


    /**
     * 产生式
     *
     * @param leftSide  左部
     * @param rightSide 右部
     */
    record Production(NonTerminal leftSide, List<Symbol> rightSide) {
    }

    /**
     * @return 开始符号
     */
    Symbol getStartSymbol();

    /**
     * @return 终结符
     */
    Set<Terminal> getTerminals();

    /**
     * @return 非终结符
     */
    Set<NonTerminal> getNonTerminals();

    /**
     * @return 产生式
     */
    List<Production> getProductions();

    /**
     * 返回满足指定表达式的符号
     *
     * @param expression 指定表达式
     * @return 满足指定表达式的符号
     */
    Symbol getSymbol(String expression);


    /**
     * @param symbols 指定子表达式
     * @return 对应的 first 集
     */
    Set<Terminal> fist(Symbol... symbols);


}
